%% @author chenkangmin


-module(cus_dump).

-behaviour(gen_server).

-export([init/1,
         handle_call/3,
         handle_cast/2,
         handle_info/2,
         terminate/2,
         code_change/3]).


-export([start_link/0,
         clean/0,
         add_module/1,
         delete_module/1
        ]).


-include("logger.hrl").
-include("ejabberd.hrl").

-record(state, {dump_timer = none, dump_module = []}).

 -define(BASE, 2).

clean() ->
    gen_server:cast(?MODULE, clean).


add_module(Module) ->
    gen_server:cast(?MODULE, {add_module, Module}).


delete_module(Module) ->
    gen_server:cast(?MODULE, {delete_module, Module}).


start_link() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).



init([]) ->
    Timer = erlang:send_after(1 * 1000, self(), auto_dump),
    ?INFO_MSG("cus auto dump service start success", []),
    {ok, #state{dump_timer = Timer, dump_module = default_modules()}}.


handle_call(_Request, _From, State) ->
    {reply, ok, State}.


handle_cast(clean, State) ->
    dump(State#state.dump_module),
    {noreply, State};

handle_cast({add_module, Module}, #state{dump_module = Modules} = State) ->
    case erlang:function_exported(Module, dump, 0) of
        true ->
            {noreply, State#state{dump_module = [Module | Modules]}};
        _ ->
            ?ERROR_MSG("~p:dump() FUNCTION IS UNEXPORTED", [Module]),
            {noreply, State}
    end;
    
handle_cast({delete_module, Module}, #state{dump_module = Modules} = State) ->
    {noreply, State#state{dump_module = lists:delete(Module, Modules)}};

handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info(auto_dump, State) ->
    if State#state.dump_timer /= none ->
            auto_dump(State#state.dump_module);
        true ->
            skip
    end,
    Timer = erlang:send_after(1 * 1000, self(), auto_dump),
    {noreply, State#state{dump_timer = Timer}};
    
handle_info(_Info, State) ->
    {noreply, State}.


terminate(_Reason, _State) ->
    ok.


code_change(_OldVsn, State, _Extra) ->
    {ok, State}.


default_modules() ->
    case erlang:function_exported(cus_conversation, dump, 0) of
        true ->
            [cus_conversation];
        _ ->
            ?ERROR_MSG("~p:dump() FUNCTION IS UNEXPORTED", [cus_conversation]),
            []
    end.


auto_dump(Modules) ->
    {_, {H, M, S}} = erlang:localtime(),
    Result = H rem ?BASE,
    case {Result, M, S} of
        {0, 0, 0} ->
            dump(Modules);
        _ ->
            skip
    end.

    
dump(Modules) ->
    ?INFO_MSG("================DUMP BEGIN===============~n", []),
    dump_module(Modules),
    ?INFO_MSG("================DUMP END=================~n", []).


dump_module([]) ->
    skip;
dump_module([Module | T]) ->
    Module:dump(),
    dump_module(T).


